package com.alks.function.service.impl.stockdept.pcfactorystockquery;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.service.RedisService;
import com.alks.common.utils.beanutils.ArrayUtils;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.entity.data.entity.PcSlipDetailPartBf;
import com.alks.entity.data.entity.PcSlipTempPartBf;
import com.alks.entity.data.entity.SdMaterialPart;
import com.alks.entity.data.entity.pcMtlAccPartBf;
import com.alks.entity.data.page.PageRecord;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.InDataException;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.CsmDetailDto;
import com.alks.function.data.request.stockdept.pcfactorystockwork.CsmDetAddRequest;
import com.alks.function.data.request.stockdept.pcfactorystockwork.CsmDetRequest;
import com.alks.function.data.request.stockdept.pcfactorystockwork.CsmMtlAddRequest;
import com.alks.function.mapper.stockdept.pcfactorystockquery.*;
import com.alks.function.service.stockdept.pcfactorystockquery.IConsumInService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.alks.entity.data.enums.ResultCodeEnum.DATA_IS_ERR;
import static com.alks.entity.data.enums.ResultCodeEnum.INPUT_ERROR;

@Service
@Slf4j
@RequiredArgsConstructor
public class ConsumInServiceImpl extends ServiceImpl<SD_SQ_PcSlipTempPartBfMapper, PcSlipTempPartBf> implements IConsumInService {
    private final SD_SQ_PcMtlAccPartBfMapper accMapper;
    private final SD_SQ_PcSlipDetailPartBfMapper detailMapper;
    private final SD_SQ_PcSlipPartReasonMapper reasonMapper;
    private final SD_SQ_PcSlipTempPartBfMapper tempMapper;
    private final SD_SQ_SdMaterialPartMapper materialMapper;
    private final SD_SQ_SdStyleTypeMapper typeMapper;
    private final RedisService redisService;

    @Override
    public ResponseInfo getCsmInTempQuery() {
        String companyId = UserIdThread.get().getCompanyId();
        /*获取数据*/
        List<PcSlipTempPartBf> temps = lambdaQuery().eq(PcSlipTempPartBf::getSlipType, "I")
                .eq(PcSlipTempPartBf::getSysUser, UserIdThread.get().getLoginName())
                .eq(PcSlipTempPartBf::getCompanyId,companyId).list();
        List<CsmTempDto> dtos = BeanUtil.copyList(temps, CsmTempDto.class);
        return ResponseInfo.ok(dtos);
    }

    @Override
    public ResponseInfo csmMtlNoCreat(String mtlTypeNo) {
        String companyId = UserIdThread.get().getCompanyId();
        /*获取最大的mtlNo*/
        String mtlNo = materialMapper.selectMtlMax(mtlTypeNo,companyId);
        /*拆分与组合数据*/
        int i = Integer.parseInt(mtlNo.substring(2, 9)) + 1;
        String dto = mtlTypeNo + String.format("%07d", i);
        return ResponseInfo.ok(dto, null);
    }

    @Override
    @Transactional
    public ResponseInfo csmMtlCreat(CsmMtlAddRequest request) {
        String mtlNoStart = "P";
        String companyId = UserIdThread.get().getCompanyId();
        if (StringUtils.isBlank(request.getMtlNo())){
            throw new ServiceErrorException("物料编号不能为空");
        }if (!request.getMtlNo().startsWith(mtlNoStart)){
            throw new ServiceErrorException("只能耗品配件");
        }if (StringUtils.isBlank(request.getMtlName())){
            throw new ServiceErrorException("物料名称不能为空");
        }
        /*判断mtlNo是否存在*/
        LambdaQueryWrapper<SdMaterialPart> wrapper = new LambdaQueryWrapper<SdMaterialPart>()
                .eq(SdMaterialPart::getMtlNo, request.getMtlNo());
        if (materialMapper.selectCount(wrapper) > 0) {
            return ResponseInfo.error("物料编号已存在，请重新生成", INPUT_ERROR.getCode());
        }
        /*写入库表数据*/
        SdMaterialPart material = BeanUtil.copyBean(request, SdMaterialPart.class);
        material.setCompanyId(companyId);
        material.setSysDate(LocalDateTime.now());
        material.setSysUser(UserIdThread.get().getLoginName());
        materialMapper.insert(material);
        /*库存建档*/
        pcMtlAccPartBf accPart = BeanUtil.copyBean(request, pcMtlAccPartBf.class);
        accPart.setCompanyId(companyId);
        accPart.setStockNo("X2");
        accMapper.insert(accPart);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo csmMtlDelete(String mtlNo) {
        String companyId = UserIdThread.get().getCompanyId();
        /*删除数据*/
        LambdaQueryWrapper<SdMaterialPart> wrapper = new LambdaQueryWrapper<SdMaterialPart>()
                .eq(SdMaterialPart::getMtlNo, mtlNo)
                .eq(SdMaterialPart::getCompanyId,companyId);
        materialMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo csmInTempAdd(String mtlNo) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String loginName = tokenDTO.getLoginName();
        String companyId = tokenDTO.getCompanyId();
        /*判断是否存在*/
        Integer count = lambdaQuery()
                .eq(PcSlipTempPartBf::getSlipType, "I")
                .eq(PcSlipTempPartBf::getSysUser, loginName)
                .eq(PcSlipTempPartBf::getCompanyId,companyId)
                .eq(PcSlipTempPartBf::getMtlNo, mtlNo).count();
        if (count > 0) {
            return ResponseInfo.error("物料已存在", INPUT_ERROR.getCode());
        }
        /*获取需要添加的数据*/
        LambdaQueryWrapper<SdMaterialPart> wrapper = new LambdaQueryWrapper<SdMaterialPart>()
                .eq(SdMaterialPart::getMtlNo, mtlNo)
                .eq(SdMaterialPart::getCompanyId,companyId);
        SdMaterialPart part = materialMapper.selectOne(wrapper);
        /*写入数据*/
        PcSlipTempPartBf temp = BeanUtil.copyBean(part, PcSlipTempPartBf.class);
        temp.setStockNo("X2");
        temp.setItem(1);
        temp.setSlipType("I");
        temp.setSysUser(loginName);
        temp.setSysDate(LocalDateTime.now());
        tempMapper.insert(temp);
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo csmInTempUpdate(String mtlNo, BigDecimal qty, String remark) {
        /*更新数据*/
        lambdaUpdate().eq(PcSlipTempPartBf::getMtlNo, mtlNo)
                .set(PcSlipTempPartBf::getQty, qty)
                .set(PcSlipTempPartBf::getRemark, remark)
                .update();
        return ResponseInfo.ok();
    }

    @Override
    public ResponseInfo csmInTempDelete(String mtlNo) {
        /*删除对应数据*/
        LambdaQueryWrapper<PcSlipTempPartBf> wrapper = new LambdaQueryWrapper<PcSlipTempPartBf>()
                .eq(PcSlipTempPartBf::getMtlNo, mtlNo)
                .eq(PcSlipTempPartBf::getSlipType, "I")
                .eq(PcSlipTempPartBf::getSysUser, UserIdThread.get().getLoginName());
        tempMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    @Override
    @AutoPageAop
    public PageRecord<CsmDetailDto> getCsmInDetailQuery(CsmDetRequest request) {
        /*获取数据*/
        LambdaQueryWrapper<PcSlipDetailPartBf> wrapper = new LambdaQueryWrapper<PcSlipDetailPartBf>()
                .eq(request.getSlipNo() != null && !request.getSlipNo().isEmpty(), PcSlipDetailPartBf::getSlipNo, request.getSlipNo())
                .eq(request.getSlipReason() != null && !request.getSlipReason().isEmpty(), PcSlipDetailPartBf::getSlipReason, request.getSlipReason())
                .eq(request.getVendorNo() != null && !request.getVendorNo().isEmpty(), PcSlipDetailPartBf::getVendorNo, request.getVendorNo())
                .ge(request.getSlipDateStart() != null, PcSlipDetailPartBf::getSlipDate, request.getSlipDateStart())
                .le(request.getSlipDateEnd() != null, PcSlipDetailPartBf::getSlipDate, request.getSlipDateEnd())
                .ge(request.getSysDateStart() != null, PcSlipDetailPartBf::getSysDate, request.getSysDateStart())
                .le(request.getSysDateEnd() != null, PcSlipDetailPartBf::getSysDate, request.getSysDateEnd())
                .eq(request.getMtlName() != null && !request.getMtlName().isEmpty(), PcSlipDetailPartBf::getMtlName, request.getMtlName())
                .eq(request.getLotNo() != null && !request.getLotNo().isEmpty(), PcSlipDetailPartBf::getLotNo, request.getLotNo())
                .eq(PcSlipDetailPartBf::getSysUser, UserIdThread.get().getLoginName())
                .eq(PcSlipDetailPartBf::getSlipType, "I")
                .orderByDesc(PcSlipDetailPartBf::getSysDate);
        List<PcSlipDetailPartBf> detail = detailMapper.selectList(wrapper);
        /*提取数据*/
        List<CsmDetailDto> dtos = BeanUtil.copyList(detail, CsmDetailDto.class);
        dtos.stream().forEach(a -> a.setSysUser(UserIdThread.get().getUserName()));
        PageRecord<CsmDetailDto> record = new PageRecord<>(dtos);
        return record;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseInfo csmInDetailDelete(String mtlNo, String slipNo) {
        String companyId = UserIdThread.get().getCompanyId();
        if (StringUtils.isEmpty(mtlNo)) {
            log.error("\n错误接口：csmInDetailDelete\n错误原因：入参不完整\n物料编码：{}  订单号：{}",mtlNo,slipNo);
            throw new InDataException("请选择要删除的单据");
        }
        /*查找数据*/
        LambdaQueryWrapper<PcSlipDetailPartBf> wrapper = new LambdaQueryWrapper<PcSlipDetailPartBf>()
                .eq(PcSlipDetailPartBf::getCompanyId,companyId)
                .eq(PcSlipDetailPartBf::getMtlNo, mtlNo)
                .eq(PcSlipDetailPartBf::getSlipNo, slipNo)
                .eq(PcSlipDetailPartBf::getSysUser, UserIdThread.get().getLoginName())
                .eq(PcSlipDetailPartBf::getSlipType, "I");
        Map<String, BigDecimal> mtlQtys = detailMapper.selectList(wrapper)
                .stream().collect(Collectors.toMap(PcSlipDetailPartBf::getMtlNo, a->BigDecimal.valueOf(a.getQty())));
        /*判断库存是否存在*/
        ArrayList<String> mtlNos = new ArrayList<>(mtlQtys.keySet());
        List<String> mtlFinds = accMapper.mtlNoDocumentCheck(mtlNos, companyId);
        List<String> miss = ArrayUtils.findMiss(mtlNos, mtlFinds);
        if (!ArrayUtils.isEmpyt(miss)) {
            log.error("\n错误接口：csmInDetailDelete\n错误原因：已入库但未找到材料建档数据\n表：PC_MTL_ACC_PART_BF\n物料ID：{}",miss);
            return ResponseInfo.error("库存异常", DATA_IS_ERR.getCode());
        }
        /*回滚库存*/
        accMapper.stkReduceByMap(mtlQtys, companyId);
        /*删除数据*/
        detailMapper.delete(wrapper);
        return ResponseInfo.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseInfo csmInDetailAdd(CsmDetAddRequest request) {
        SysUserTokenDTO tokenDTO = UserIdThread.get();
        String companyId = tokenDTO.getCompanyId();
        String loginName = tokenDTO.getLoginName();
        /*查询数据*/
        LambdaQueryWrapper<PcSlipTempPartBf> wrapper = new LambdaQueryWrapper<PcSlipTempPartBf>()
                .eq(PcSlipTempPartBf::getCompanyId, companyId)
                .eq(PcSlipTempPartBf::getSysUser, loginName)
                .ge(PcSlipTempPartBf::getQty, 0)
                .eq(PcSlipTempPartBf::getSlipType, "I");
        List<PcSlipTempPartBf> temps = tempMapper.selectList(wrapper);
        /*判断是否存在*/
        if (ArrayUtils.isEmpyt(temps)) {
            return ResponseInfo.error("待入库没有数量大于0的数据", INPUT_ERROR.getCode());
        }
        List<PcSlipDetailPartBf> details = BeanUtil.copyList(temps, PcSlipDetailPartBf.class);
        String slipNo = redisService.slipNoCreat("X");
        /*补充参数*/
        for (PcSlipDetailPartBf detail : details) {
            detail.setSlipNo(slipNo);
            detail.setDeptNo(request.getDeptNo());
            detail.setDeptName(request.getDeptName());
            detail.setVendorNo(request.getVendorNo());
            detail.setVendorName(request.getVendorName());
            detail.setSlipDate(request.getSlipDate().atStartOfDay());
            detail.setSlipReason(request.getSlipReason());
            detail.setSysUser(loginName);
            detail.setSysDate(request.getSysDate() == null ? LocalDateTime.now() : request.getSysDate().atStartOfDay());
            detail.setSendNo(request.getSendNo());
            /*写入明细数据*/
            detailMapper.insert(detail);
        }
        /*判断是否建档并写入库存数据*/
        Map<String, BigDecimal> mtlQtys = temps.stream()
                .collect(Collectors.toMap(PcSlipTempPartBf::getMtlNo, a -> BigDecimal.valueOf(a.getQty())));
        List<String> mtlNos = new ArrayList<>(mtlQtys.keySet());
        List<String> mtlFinds = accMapper.mtlNoDocumentCheck(mtlNos, companyId);
        List<String> miss = ArrayUtils.findMiss(mtlNos, mtlFinds);
        /*建档*/
        if (!ArrayUtils.isEmpyt(miss)) {
            accMapper.insertByTemp(miss, companyId);
        }
        accMapper.stkInByMap(mtlQtys, companyId);
        /*删除原表数据*/
        tempMapper.delete(wrapper);
        return ResponseInfo.ok();
    }
}
